<?php

	namespace app\controller\pos;

	use app\event\app\Device;
	use app\event\store\User as UserEvent;
	use app\model\ucenter\User as UserModel;
	use GatewayWorker\Lib\Gateway;
	use think\Db;
	use think\Exception;
	use think\facade\Cache;
	use think\facade\Log;
	use think\worker\Application;
	use app\event\im\Chat as ChatEvent;
	use Workerman\Connection\TcpConnection;
	use Workerman\Lib\Timer;
	use Workerman\Worker;

	class GatewayWorker
	{

		/**
		 * onConnect 事件回调
		 * 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
		 * @access public
		 * @param int $client_id
		 * @return void
		 */
		public static function onConnect($client_id)
		{
			Gateway::sendToCurrentClient(self::_formatData('connect ok', 'init'));
			//:todo 通知好友上线
		}


		/**
		 * onMessage 事件回调
		 * 当客户端发来数据(Gateway进程收到数据)后触发
		 * @access public
		 * @param int $client_id
		 * @param mixed $data
		 * @return void
		 */
		public static function onMessage($client_id, $data)
		{
			$type = 'replay';
			try {
				Log::channel('socket')->info($data);
				if (!self::dataCheck($data)) {
					$result = 'data error';
				} else {
					$data = json_decode($data, true);
					// 发送消息
					$user = self::_getBindUser($client_id);
					$event = new ChatEvent();
					if ('bind_id' == $data['type']) {
						// 查询用户
						$event = new UserEvent();
//						$uResult = $event->getInfoByToken($data['data']['token']);
						$uResult = $event->getInfoByToken('c22442c7585affd1bf0b5497db7893f1');
						if ($uResult['code'] !== 0) {
							throw new Exception('no user');
						}
						$user = $uResult['data'];
						if ($user['id'] != $data['data']['id']) {
							throw new Exception('信息异常');
						}
						Gateway::bindUid($client_id, $data['data']['id']);
						$result = ['chat' => '绑定成功', 'client_id' => $client_id];
					} elseif ('get_chat_detail' == $data['type']) {
						$result = $event->detail($data, $user);
					} elseif ('single_chat' == $data['type']) {
						$send = $data;
						$send['ip'] = $_SERVER['REMOTE_ADDR'];
						$result = $event->send($send, $user);
						// 发送对方消息
						if ($result['code'] == 0) {
							self::_sendChatMessage($result['data']);
						}
						$type = 'send_single_chat_success';
					} elseif ('read_single_chat' == $data['type']) {
						// 用户已读
						$event = new ChatEvent();
						$result = $event->readAll($data, $user);
					} elseif ('ping' == $data['type']) {
						$result = 'success';
                        $type = 'ping_success';
					} else {
						$result = '未知消息类型';
						$type = 'error';
					}
				}
			} catch (\Exception $e) {
				$result = 'file:' . $e->getFile() . ',message:' . $e->getMessage() . ',line:' . $e->getMessage();
				$type = 'exception';
			}
			Gateway::sendToCurrentClient(self::_formatData($result, $type));
		}

		/**
		 * 获取绑定用户
		 * @param $client_id
		 * @return UserModel|null
		 */
		protected static function _getBindUser($client_id)
		{
			$uid = GateWay::getUidByClientId($client_id);
			if ($uid)
			{
				return UserModel::where('id', $uid)->find();
			}else{
				return null;
			}
		}

		/**
		 * onClose 事件回调 当用户断开连接时触发的方法
		 * @param integer $client_id 断开连接的客户端client_id
		 * @return void
		 */
		public static function onClose($client_id)
		{
			// :TODO 通知用户离线
//			GateWay::sendToAll("client[$client_id] logout\n");
		}

		/**
		 * onWorkerStart 事件回调
		 * 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
		 * @access public
		 * @param \Workerman\Worker $businessWorker
		 * @return void
		 */
		public static function onWorkerStart(Worker $businessWorker)
		{
			$app = new Application;
			$app->initialize();
			// 0.1秒一次轮询
			Timer::add(0.5, function () use ($businessWorker) {
				$time_now = time();
			});
		}


		/**
		 * onWebSocketConnect 事件回调
		 * 当客户端连接上gateway完成websocket握手时触发
		 * @param integer $client_id 断开连接的客户端client_id
		 * @param mixed $data
		 * @return void
		 */
		public static function onWebSocketConnect($client_id, $data)
		{
			var_export($client_id);
			echo $client_id . "\n";
//			var_export($data);
		}

		/**
		 * onWorkerStop 事件回调
		 * 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
		 * @param \Workerman\Worker $businessWorker
		 * @return void
		 */
		public static function onWorkerStop(Worker $businessWorker)
		{
			echo "WorkerStop\n";
//			Log::channel('socket')->error('msg ' . $msg . ' error ' . $code);
		}

		/**
		 *  发送对方消息
		 * @param $data
		 */
		protected static function _sendChatMessage($data)
		{
			$chat = $data['to_chat'];
			// 查询对方在线设备
			$clients = Gateway::getClientIdByUid($chat['to_user_id']);
			if (count($clients) > 0) {
				// 联系人在线
				foreach ($clients as $client) {
					Gateway::sendToUid($client, self::_formatData($chat, 'receive_single_chat'));
				}
			} else {
				// 没在线，发送推送
				$device = new Device();
				$param['type'] = 'receive_single_chat';
				$param['title'] = $data['result']['myChat']['user']['nickname'];
				$param['body'] = $data['result']['content']['content'];
				$param['relation_id'] = $data['result']['content']['id'];
				$device->pushToSingleUser($param, $data['to_chat']['user']);
			}
		}

		public function onWorkerReload($worker)
		{
			// 重启服务
		}

		/**
		 * 数据格式化
		 * @param               $data
		 * @param  $type
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private static function _formatData($data, $type): string
		{
			$_data = [
				'time' => time(),
				'type' => $type,
				'data' => $data
			];
			Log::error('send ' . json_encode($_data));
			return json_encode($_data);
		}


		private static function dataCheck($data)
		{
			json_decode($data);
			return (json_last_error() == JSON_ERROR_NONE) && !is_numeric($data);
		}
	}